#include "image.h"

/******************************************************************************
 Create Height Map and Load Textures
 ******************************************************************************/

/*
 *    Take the name of a file, along with the dimensions of the file and read
 *    the data from a .raw image file.
 */
void loadRawImage(textureFile& texture)
{
   texture.texture = new GLbyte[texture.width * texture.height * 3];
   
   // Read the file in binary mode.
   FILE* file = fopen(texture.filename.c_str(), "rb");
   
   //    Reads the entire file at once.
   if (file)
   {
      fread(texture.texture, 1, texture.width * texture.height * 3, file);
      fclose(file);
   }
   else cerr << "Error opening " << texture.filename << endl;
}

/*
 *    Loads a grayscale raw image file into a 2D image buffer.
 */
GLbyte** loadRawImage(heightFile& height)
{
   //    Read the file in binary mode
   FILE* file = fopen(height.filename.c_str(), "rb");
   
   GLbyte** data = new GLbyte*[height.width];
   
   //    Read the file one row at a time.
   if (file)
   {
      for (int i = 0; i < height.width; ++i)
      {
         data[i] = new GLbyte[height.height];
         fread(data[i], 1, height.height, file);
      }
      fclose(file);
      return data;
   }
   else 
   {
      cerr << "Error opening " << height.filename << endl;
      return NULL;
   }  
}

/*
 *    Read data from a grayscale image and convert it to a height map.
 */
void getHeightMap(heightFile& file)
{
   GLbyte** data = loadRawImage(file);
   
   if (data)
   {
      // Number of pixels.
      file.map = new float*[file.width];
      
      for (int i = 0; i < file.width; ++i)
         file.map[i] = new float[file.height];
      
      // Grab the data from the image, then scale it from percent to decimal.
      for (int i = 0; i < file.width; ++i)
      {
         for(int j = 0; j < file.height; ++j)
         {
            file.map[i][j] = (unsigned char)data[i][j] / (float)255;
         }
      }
   }
   else
   {
      cerr << "Height file not found. Exiting..." << endl;
      exit(1);
   }
}

/*
 *    Take a texture and generate an ID and bind the texture in OpenGL.
 *    Currently, code is implemented in the individual functions and this
 *    function is never called.
 */
void makeTexture(textureFile& texture)
{
   //    Generate a texture ID and bind the texture.
   glGenTextures(1, &texture.id);
   glBindTexture(GL_TEXTURE_2D, texture.id);
   
   //    Create the texture from the image buffer and create mipmaps for it.
   glTexImage2D(GL_TEXTURE_2D, 0, 3, texture.width, texture.height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture.texture);
   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, texture.width, texture.height, GL_RGB, GL_UNSIGNED_BYTE, texture.texture);
   
   //    More parameters for the texture.
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	// Linear Filtering
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);	// Linear Filtering

   //    Unbind the texture.
   glBindTexture(GL_TEXTURE_2D, 0);
   
   //    Delete the data from the texture to save memory.
   delete[] texture.texture;
}
